App.require(function () {
    var strComponents = [{
            name: "str-icon",
            js: "/public/ui/component/str-icon/index.js"
        },
        {
            name: "str-btn",
            js: "/public/ui/component/str-btn/index.js"
        },
        {
            name: "str-float-btn",
            js: "/public/ui/component/str-float-btn/index.js"
        },
        {
            name: "str-form",
            js: "/public/ui/component/str-form/index.js"
        },
        {
            name: "str-text",
            js: "/public/ui/component/str-text/index.js"
        },
        {
            name: "str-textarea",
            js: "/public/ui/component/str-textarea/index.js"
        },
        {
            name: "str-range",
            js: "/public/ui/component/str-range/index.js"
        },
        {
            name: "str-toggle",
            js: "/public/ui/component/str-toggle/index.js"
        },
        {
            name: "str-date",
            js: "/public/ui/component/str-date/index.js"
        },
        {
            name: "str-date-area",
            js: "/public/ui/component/str-date-area/index.js"
        },
        {
            name: "str-menu-list",
            js: "/public/ui/component/str-menu-list/index.js"
        },
        {
            name: "str-select",
            js: "/public/ui/component/str-select/index.js"
        },
        {
            name: "str-native-select",
            js: "/public/ui/component/str-native-select/index.js"
        },
        {
            name: "str-uploader",
            js: "/public/ui/component/str-uploader/index.js"
        },
        {
            name: "str-progress",
            js: "/public/ui/component/str-progress/index.js"
        },
        {
            name: "str-down-fresh",
            js: "/public/ui/component/str-down-fresh/index.js"
        },
        {
            name: "str-uploader-container",
            js: "/public/ui/component/str-uploader-container/index.js"
        },
        {
            name: "str-tab",
            js: "/public/ui/component/str-tab/index.js"
        },
        {
            name: "str-chip",
            js: "/public/ui/component/str-chip/index.js"
        },
        {
            name: "str-stepper",
            js: "/public/ui/component/str-stepper/index.js"
        },
        {
            name: "str-card",
            js: "/public/ui/component/str-card/index.js"
        },
        {
            name: "str-list",
            js: "/public/ui/component/str-list/index.js"
        },
        {
            name: "str-bottom-nav",
            js: "/public/ui/component/str-bottom-nav/index.js"
        },
        {
            name: "str-top-bar",
            js: "/public/ui/component/str-top-bar/index.js"
        },
        {
            name: "str-aside-nav",
            js: "/public/ui/component/str-aside-nav/index.js"
        },
        {
            name: "str-img",
            js: "/public/ui/component/str-img/index.js"
        },
        {
            name: "str-table",
            js: "/public/ui/component/str-table/index.js"
        },
        {
            name: "str-data-table",
            js: "/public/ui/component/str-data-table/index.js"
        },
        {
            name: "str-canvas",
            js: "/public/ui/component/str-canvas/index.js"
        },
        {
            name: "str-pagination",
            js: "/public/ui/component/str-pagination/index.js"
        },
        {
            name: "str-tree",
            js: "/public/ui/component/str-tree/index.js"
        }
    ];

    var strPopUps = [{
            name: "strdatePicker",
            js: "/public/ui/popup/datePicker/index.js",
            staticName: "strdatePickerLayout",
            activeName: "strdatePickerActive",
            config: {
                className: "date-picker-container"
            }
        }, {
            name: "strdatetimePicker",
            js: "/public/ui/popup/datetimePicker/index.js",
            staticName: "strdatetimePickerLayout",
            activeName: "strdatetimePickerActive",
            config: {
                className: "date-picker-container"
            }
        },{
            name: "strdateRangePicker",
            js: "/public/ui/popup/dateRangePicker/index.js",
            staticName: "strdateRangePickerLayout",
            activeName: "strdateRangePickerActive",
            config: {
                className: "date-range-picker-container"
            }
        }, {
            name: "strmenulist",
            js: "/public/ui/popup/menulist/index.js",
            staticName: "strmenulistlayout",
            activeName: "strmenulistactive",
            config: {
                className: "str-menulist"
            }
        }, {
            name: "strtoast",
            js: "/public/ui/popup/toast/index.js",
            staticName: "strtoastlayout",
            activeName: "strtoastactive",
            config: {
                className: "toast",
                currentIn: {
                    backClass: "down-up",
                    changeClass: "down-down"
                }
            },
        },
        {
            name: "strdialog",
            js: "/public/ui/popup/dialog/index.js",
            staticName: "strdialoglayout",
            activeName: "strdialogactive",
            config: {
                className: "dialog",
                currentIn: {
                    backClass: "opacityIn",
                    changeClass: "opacityOut"
                }
            }
        },
        {
            name: "areaselect",
            js: "/public/ui/popup/areaselect/index.js",
            staticName: "areaselectlayout",
            activeName: "areaselectactive",
            config: {
                className: "area-select-dialog",
                currentIn: {
                    backClass: "opacityIn",
                    changeClass: "opacityOut"
                }
            }
        },
        {
            name: "strpagedialog",
            js: "/public/ui/popup/pageDialog/index.js",
            staticName: "strpagelayout",
            config: {
                className: "pagedialog",
                currentIn: {
                    backClass: "opacityIn",
                    changeClass: "opacityOut"
                }
            }
        },
        {
            name: "strfulldialog",
            js: "/public/ui/popup/fulldialog/index.js",
            staticName: "strfulldialoglayout",
            config: {
                className: "fulldialog",
                currentIn: {
                    backClass: "opacityIn",
                    changeClass: "opacityOut"
                }
            }
        },
        {
            name: "strloader",
            js: "/public/ui/popup/loader/index.js",
            staticName: "strloaderlayout",
            activeName: "strloaderactive",
            config: {
                className: "str-loader",
                currentIn: {
                    backClass: "opacityIn",
                    changeClass: "opacityOut"
                }
            }
        },
        {
            name: "strpcdatePicker",
            js: "/public/ui/popup/pcdatePicker/index.js",
            staticName: "strpcdatapickerlayout",
            activeName: "strpcdataPickerActive",
            config: {
                className: "str-pc-date-picker-container",
                currentIn: {
                    backClass: "scaleUp",
                    changeClass: "scaleDown"
                }
            }
        },
        {
            name: "pcstrdateRangePicker",
            js: "/public/ui/popup/pcdatarangePicker/index.js",
            staticName: "strpcdatarangepickerlayout",
            activeName: "strpcdatarangePickerActive",
            config: {
                className: "str-pc-date-range-picker-container",
                currentIn: {
                    backClass: "scaleUp",
                    changeClass: "scaleDown"
                }
            }
        },
        {
            name: "pcareaselect",
            js: "/public/ui/popup/pcareaselect/index.js",
            staticName: "pcareaselectlayout",
            activeName: "pcareaselectactive",
            config: {
                className: "str-pc-area-select-container",
            }
        }
    ];

    var strLayers = [
        {
            name: "str-img-layer",
            js: "/public/ui/layers/str-img-layer/index.js"
        },
        {
            name: "str-btn-layer",
            js: "/public/ui/layers/str-btn-layer/index.js"
        },
        {
            name: "str-radio-btn-group-layer",
            js: "/public/ui/layers/str-radio-btn-group-layer/index.js"
        },
        {
            name: "str-text-layer",
            js: "/public/ui/layers/str-text-layer/index.js"
        },
        {
            name: "str-linear-gradient",
            js: "/public/ui/layers/str-linear-gradient/index.js"
        },
        {
            name: "str-radial-gradient",
            js: "/public/ui/layers/str-radial-gradient/index.js"
        },
        {
            name: "str-layer",
            js: "/public/ui/layers/str-layer/index.js"
        },
        {
            name: "str-img-pattern",
            js: "/public/ui/layers/str-img-pattern/index.js"
        },
        {
            name: "str-rect-layer",
            js: "/public/ui/layers/str-rect-layer/index.js"
        },
        {
            name: "str-path-layer",
            js: "/public/ui/layers/str-path-layer/index.js"
        },
        {
            name: "str-render-layer",
            js: "/public/ui/layers/str-render-layer/index.js"
        },
        {
            name: "str-column-chart",
            js: "/public/ui/layers/str-column-chart/index.js"
        },
        {
            name: "str-pie-chart",
            js: "/public/ui/layers/str-pie-chart/index.js"
        },
        {
            name: "str-line-chart",
            js: "/public/ui/layers/str-line-chart/index.js"
        },
        {
            name: "str-radar-chart",
            js: "/public/ui/layers/str-radar-chart/index.js"
        },
        {
            name: "str-marker-layer",
            js: "/public/ui/layers/str-marker-layer/index.js"
        },
        {
            name: "str-animation-layer",
            js: "/public/ui/layers/str-animation-layer/index.js"
        },
        {
            name: "str-scatter-chart",
            js: "/public/ui/layers/str-scatter-chart/index.js"
        },
        {
            name: "str-heat-chart",
            js: "/public/ui/layers/str-heat-chart/index.js"
        },
        {
            name: "str-relative-chart",
            js: "/public/ui/layers/str-relative-chart/index.js"
        },
        {
            name: "str-funnel-chart",
            js: "/public/ui/layers/str-funnel-chart/index.js"
        },
        {
            name: "str-dashboard-chart",
            js: "/public/ui/layers/str-dashboard-chart/index.js"
        }
    ];

    App.prototype.showMenulist = function (list, cssString, page, selfData, isBack) {
        isBack = isBack || false, page = page || App.getCurrent().currentPage.name;
        selfData = selfData || {};
        var result = {
            list: list,
            cssString: cssString,
            pagename: page
        };
        for (var key in selfData) {
            result[key] = selfData[key];
        }
        this.showPopUp("strmenulist",result, isBack);
    };

    App.prototype.showToast = function (message, backstr, timeout, pagename, mark, isNow) {
        this.showPopUp("strtoast", {
            message: message,
            cancel: backstr || "",
            timeout: timeout,
            pagename: pagename || App.getCurrent().currentPage.name,
            mark: mark || "",
            isNow: isNow
        }, true);
    };

    Page.prototype.showDialog = function (message, config) {
        config = config || {};
        config.message = message;
        if (!config.actions) config.actions = [
            { action: "cancel", content: "取消" },
            { action: "confirm", content: "确认" }
        ];
        this.showPopUp("strdialog", config);
    };

    App.prototype.showPageDialog = function (pagename, config, isBack) {
        config = config || {};
        config.mask = config.mask || "";
        config.cssString = config.cssString || "";
        config.pagename = pagename;
        config.currentpage = config.currentPage || this.currentPage.name;
        this.showPopUp("strpagedialog", config, isBack);
    }

    Page.prototype.showPageDialog = function (pagename, config) {
        config = config || {};
        config.mask = config.mask || "";
        config.cssString = config.cssString || "";
        config.pagename = pagename;
        this.showPopUp("strpagedialog", config);
    }

    Page.prototype.showFullDialog = function (pagename, config) {
        config = config || {};
        config.cssString = config.cssString || "";
        config.pagename = pagename;
        config.overflow = typeof config.overflow === "undefined" ? "content-save" : config.overflow;
        this.showPopUp("strfulldialog", config);
    }

    Page.prototype.showAreaSelect = function(name, options) {
        var data = {},
            options = options || {};
        for (var key in options) {
            data[key] = options[key];
        }
        data.origin = name;
        if (window.innerWidth < 800) {
            this.showPopUp("areaselect", data);
        }
        else {
            if (!options.cssStr) {
                if (options.targetDom) {
                    var rect = options.targetDom.getBoundingClientRect();
                    var leftCss = "", topCss = "";
                    if (window.innerHeight - rect.bottom > 198) {
                        topCss = "top: " + (rect.bottom + 4) + "px";
                    }
                    else {
                        topCss = "top: " + (rect.top - 204) + "px";
                    }
                    if (window.innerWidth - rect.right > 204) {
                        leftCss = "left: " + rect.left + "px";
                    }
                    else {
                        leftCss = "right:" + (window.innerWidth - rect.right) + "px";
                    }
                    data.cssStr = leftCss + ";" + topCss;
                }
            }
            this.showPopUp("pcareaselect", data);
        }
    };

    App.prototype.outofHistory = function () {
        this.showLoader("再次点击后退， 退出该应用", { icon: "check", duration: 2000 });
    };

    App.prototype.showImgViewer = function (imgList, index, config) {
        config = config || { mask: true };
        config.cssString = config.cssString || "";
        config.imgList = imgList || [];
        config.index = index || 1;
        config.pagename = "strimgviewer";
        this.showPopUp("strpagedialog", config);
    };

    /**
     * 显示加载弹窗
     * @param {string} str 字符串类型
     * @param {object} option 配置对象
     * @param {function} bk 对弹窗的后续处理
     */
    App.prototype.showLoader = function (str, option, bk) {
        option = option || {};
        option.duration = option.duration || 0;
        option.icon = option.icon || false;
        this.showPopUp("strloader", {
            option: option,
            content: str,
            bk: bk
        }, true);
    };

    var strPages = [{
            name: "strdatePickerLayout",
            js: "/public/ui/popup/datePicker/pages/layout/index.js",
            title: "布局",
            url: "/strdatepicker/layout"
        },
        {
            name: "strdatePickerActive",
            js: "/public/ui/popup/datePicker/pages/index/index.js",
            title: "首页",
            url: "/strdatepicker/index"
        },
        {
            name: "strdatePickerSecond",
            js: "/public/ui/popup/datePicker/pages/second/index.js",
            title: "次页",
            url: "/strdatepicker/second"
        }, 
        {
            name: "strdatetimePickerLayout",
            js: "/public/ui/popup/datetimePicker/pages/layout/index.js",
            title: "布局",
            url: "/strdatetimepicker/layout"
        },
        {
            name: "strdatetimePickerActive",
            js: "/public/ui/popup/datetimePicker/pages/index/index.js",
            title: "首页",
            url: "/strdatetimepicker/index"
        },
        {
            name: "strdatetimePickerSecond",
            js: "/public/ui/popup/datetimePicker/pages/second/index.js",
            title: "次页",
            url: "/strdatetimepicker/second"
        }, 
        {
            name: "strdatetimePickerTime",
            js: "/public/ui/popup/datetimePicker/pages/selecttime/index.js",
            title: "选择时间",
            url: "/strdatetimepicker/selectTime"
        }, 
        {
            name: "strdateRangePickerLayout",
            js: "/public/ui/popup/dateRangePicker/pages/layout/index.js",
            title: "布局",
            url: "/strdateRangePicker/layout"
        },
        {
            name: "strdateRangePickerActive",
            js: "/public/ui/popup/dateRangePicker/pages/index/index.js",
            title: "首页",
            url: "/strdateRangePicker/index"
        },
        {
            name: "strdateRangePickerSecond",
            js: "/public/ui/popup/dateRangePicker/pages/second/index.js",
            title: "次页",
            url: "/strdateRangePicker/second"
        }, 
        {
            name: "strdaterangetimeselect",
            js: "/public/ui/popup/dateRangePicker/pages/selecttime/index.js",
            title: "选择时间",
            url: "/strdaterangepicker/selectTime"
        }, 
        {
            name: "strmenulistlayout",
            js: "/public/ui/popup/menulist/pages/layout/index.js",
            title: "列表静态页",
            url: "/strmenulist/layout"
        }, {
            name: "strmenulistactive",
            js: "/public/ui/popup/menulist/pages/index/index.js",
            title: "列表首页",
            url: "/strmenulist/index"
        }, {
            name: "strtoastlayout",
            js: "/public/ui/popup/toast/pages/layout/index.js",
            title: "提示框静态页",
            url: "/strtoast/layout"
        }, {
            name: "strtoastactive",
            js: "/public/ui/popup/toast/pages/index/index.js",
            title: "提示框首页",
            url: "/strtoast/layout"
        },
        {
            name: "strdialoglayout",
            js: "/public/ui/popup/dialog/pages/layout/index.js",
            title: "弹窗静态页",
            url: "/strdialog/layout"
        }, {
            name: "strdialogactive",
            js: "/public/ui/popup/dialog/pages/index/index.js",
            title: "弹窗首页",
            url: "/strdialog/layout"
        }, {
            name: "strpagelayout",
            js: "/public/ui/popup/pageDialog/pages/layout/index.js",
            title: "页面弹窗静态页",
            url: "/strdialog/layout"
        },
        {
            name: "strfulldialoglayout",
            js: "/public/ui/popup/fulldialog/pages/layout/index.js",
            title: "全页面弹窗静态页",
            url: "/strfulldialoglayout/layout"
        }, {
            name: "strloaderlayout",
            js: "/public/ui/popup/loader/pages/layout/index.js",
            title: "加载器弹窗静态页",
            url: "/strloader/layout"
        },
        {
            name: "strloaderactive",
            js: "/public/ui/popup/loader/pages/index/index.js",
            title: "加载器弹窗动态页",
            url: "/strloader/active"
        },
        {
            name: "strimgviewer",
            js: "/public/ui/pages/strimgviewer/index.js",
            title: "图片查看器",
            url: "/strimgviewer/active"
        }, {
            name: "areaselectlayout",
            js: "/public/ui/popup/areaselect/pages/layout/index.js",
            title: "区域选择静态页",
            url: "/areaselectlayout"
        }, {
            name: "areaselectactive",
            js: "/public/ui/popup/areaselect/pages/index/index.js",
            title: "区域选择首页",
            url: "/areaselectactive"
        }, {
            name: "strpcdatapickerlayout",
            js: "/public/ui/popup/pcdatePicker/pages/layout/index.js",
            title: "pc端选择时间布局页",
            url: "/strpcdatapickerlayout"
        }, {
            name: "strpcdataPickerActive",
            js: "/public/ui/popup/pcdatePicker/pages/index/index.js",
            title: "pc端选择时间首页",
            url: "/strpcdataPickerActive"
        },
        {
            name: "strpcselectYear",
            js: "/public/ui/popup/pcdatePicker/pages/selectYearMonh/index.js",
            title: "pc端选择年份页",
            url: "/strpcselectYear"
        },
        {
            name: "strpctimeselect",
            js: "/public/ui/popup/pcdatePicker/pages/pctimeselect/index.js",
            title: "pc端选择时间页",
            url: "/strpctimeselect"
        },
        {
            name: "strpcdatarangepickerlayout",
            js: "/public/ui/popup/pcdatarangePicker/pages/layout/index.js",
            title: "pc端选择范围静态页",
            url: "/strpcdatarangepickerlayout"
        },
        {
            name: "strpcdatarangePickerActive",
            js: "/public/ui/popup/pcdatarangePicker/pages/index/index.js",
            title: "pc端选择时间范围页",
            url: "/strpcdatarangePickerActive"
        },
        {
            name: "strdatarangeselectyearmonth",
            js: "/public/ui/popup/pcdatarangePicker/pages/selectYearMonth/index.js",
            title: "pc端选择时间范围年月页",
            url: "/strdatarangeselectyearmonth"
        },
        {
            name: "strdatarangeselecttime",
            js: "/public/ui/popup/pcdatarangePicker/pages/selectTime/index.js",
            title: "pc端选择时间页",
            url: "/strdatarangeselecttime"
        },
        {
            name: "pcareaselectlayout",
            js: "/public/ui/popup/pcareaselect/pages/layout/index.js",
            title: "pc端多组选择静态",
            url: "/pcareaselectlayout"
        },
        {
            name: "pcareaselectactive",
            js: "/public/ui/popup/pcareaselect/pages/index/index.js",
            title: "pc端多组选择活动",
            url: "/pcareaselectactive"
        }
    ];

    if ("ontouchstart" in window) {
        window.addEventListener("touchstart", touchstartHandler, false);
    } else {
        window.addEventListener("mousedown", touchstartHandler, false);
    }

    function getRippleTarget(dom) {
        var parent = dom;
        while (parent && parent.classList && !parent.classList.contains("ripple")) {
            parent = parent.parentNode;
        }

        if (parent.classList && !parent.disabled) {
            return parent;
        }
        return null;
    }

    function showRipple(div, target, touch) {
        div.className = "ripple-in";
        var rect = target.getBoundingClientRect();
        var x = touch.clientX - rect.left,
            y = touch.clientY - rect.top,
            w = rect.width,
            h = rect.height,
            l = x - w / 2,
            t = y - h / 2,
            r = Math.sqrt(w * w + h * h) + "px";

        var transformStr = "translate(-50%, -50%) translate(" + l + "px, " + t + "px)";
        div.style.cssText = "width: " + r + "; height: " + r + "; left: " + (w / 2) + "px; top: " + (h / 2) + "px";
        div.style.setProperty("--startanimation", transformStr + " scale(0)");
        div.style.setProperty("--animationend", "translate(-50%, -50%) translate(0px, 0px) scale(1)");
        target.insertBefore(div, null);
        div.classList.add("ripple-end");
    }

    function touchstartHandler(ev) {
        var target = ev.target;
        var label = Component.getNodeName(target, "LABEL");
        if (label && (label.getAttribute("role") == "toggle")) return;
        var rippleTarget = getRippleTarget(target);
        var div = document.createElement("div"),
            isTouch = ev.touches;

        if (rippleTarget) {
            if (isTouch) {
                rippleTarget.addEventListener("touchend", touchendHandler, false);
                window.addEventListener("touchmove", removeHandler, false);
                rippleTarget.addEventListener("touchcancel", touchendHandler, false);
            } else {
                rippleTarget.addEventListener("mouseup", touchendHandler, false);
            }
            showRipple(div, rippleTarget, isTouch ? ev.touches[0] : ev);
        }

        function touchendHandler(ev) {
            if (isTouch) {
                rippleTarget.removeEventListener("touchend", touchendHandler, false);
                window.removeEventListener("touchmove", removeHandler, false);
                rippleTarget.removeEventListener("touchcancel", touchendHandler, false);
            } else {
                rippleTarget.removeEventListener("mouseup", touchendHandler, false);
            }
            setTimeout(function () {
                div.classList.remove("ripple-end");
                div.classList.add("ripple-out");
                setTimeout(function () {
                    div.classList.add("ripple-remove");
                    setTimeout(function () {
                        if (rippleTarget.contains(div)) rippleTarget.removeChild(div);
                    }, 150);
                }, 150);
            }, 75);
        }

        function removeHandler(ev) {
            if (isTouch) {
                rippleTarget.removeEventListener("touchend", touchendHandler, false);
                window.removeEventListener("touchmove", removeHandler, false);
                rippleTarget.removeEventListener("touchcancel", touchendHandler, false);
            } else {
                rippleTarget.removeEventListener("mouseup", touchendHandler, false);
            }
            if (rippleTarget.contains(div)) rippleTarget.removeChild(div);
        }
    }

    App.prototype.defineLayer = function (name, obj) {
        obj.getDomObj = obj.getDomObj || function () {};
        obj.pushImageSrc = obj.pushImageSrc || function (src) {
            if (this.tagName.toUpperCase() === "str-CANVAS") this.addImgSrc(src);
            else this.parent.pushImageSrc(src);
        }
        obj.getImgBySrc = obj.getImgBySrc || function (src) {
            if (this.tagName.toUpperCase() === "str-CANVAS") return this.data.resourceMap[src];
            return this.parent.getImgBySrc(src);
        };
        obj.getGradientByStr = obj.getGradientByStr || function (str, target) {
            target = target || this;
            if (this.tagName.toUpperCase() === "str-CANVAS") {
                return this.data.gradientMap[str] || this.createGradientByStr(str, target);
            } 
            return this.parent.getGradientByStr(str, target);
        };
        obj.setGradient = obj.setGradient || function (obj) {
            if (this.tagName.toUpperCase() === "str-CANVAS") this.data.gradients.push(obj);
            else this.parent.setGradient(obj);
        };
        obj.setPattern = obj.setPattern || function (obj) {
            if (this.tagName.toUpperCase() === "str-CANVAS") this.data.patterns.push(obj);
            else this.parent.setPattern(obj);
        };
        obj.getPatternByStr = obj.getPatternByStr || function (str, target) {
            target = target || this;
            if (this.tagName.toUpperCase() === "str-CANVAS") {
                return this.data.patternMap[str] || this.createPatternByStr(str, target);
            } 
            return this.parent.getPatternByStr(str, target);
        };
        obj.draw = obj.draw || function (ctx) {
            if (this.property.hidden) return;
            ctx.save();
            if (typeof this.drawSelf === "function") {
                this.drawSelf(ctx);
            }
            var components = this.components;
            for (var i = 0; i < components.length; i++) {
                var com = components[i];
                if (typeof com.draw === "function") com.draw(ctx);
            }
            this.data.isChange = false;
            ctx.restore();
        }
        obj.getFillOrStrokeStyle = function (str) {
            if (str.indexOf("$") == 0) {
                var pattern = this.getPatternByStr(str, this);
                return pattern;
            }
            else if (str.indexOf("#") == 0) {
                var gradient = this.getGradientByStr(str, this);
                return gradient;
            }
            return str;
        };
        obj._getCanvas = function () {
            if (this.tagName.toUpperCase() === "str-CANVAS") return this;
            return this.parent._getCanvas();
        };
        obj.setValue = function (key, value) {
            if (this.property[key] === value) return false;
            this.data.isChange = true;
            this.property[key] = value;
            return true;
        };
        obj.getValue = function (key) {
            return this.property[key];
        };
        obj._getChange = function () {
            if (this.data.isChange) return true;
            var components = this.components;
            for (var i = 0; i < components.length; i++) {
                if (components[i]._getChange()) return true;
            }
            return false;
        };
        obj._changeShadowStr = function (str) {
            var pattern = /^\s*(\d+)\s+(\d+)\s+(\d+)\s+([\s\S]+?)\s*$/;
            var match = pattern.exec(str);
            if (match) {
                return {
                    x: match[1],
                    y: match[2],
                    blur: match[3],
                    color: match[4]
                }
            }
            return null;
        };
        /**
         * 将transformStr转为转换的方法
         * @param {string} str 样式字符串,支持canvas的转换方式
         * translate(10, 10) scale(2, 1) rotate(.707);
         */
        obj._getTransformList = function (str) {
            var pattern = /(translate|rotate|scale)\(([\S\s]*?)\)/g, result = [];
            var matches = pattern.exec(str);
            while (matches) {
                var tList = matches[2].split(",").map(function (item) {
                    return parseFloat(item);
                });
                result.push({
                    action: matches[1],
                    args: tList
                });
                matches = pattern.exec(str);
            }
            return result;
        };
        obj.containsBounds = obj.containsBounds || function (ctx, x, y) {
            if (typeof this.createPath === "function") {
                this.createPath(ctx);
                if (ctx.isPointInPath(x, y)) return true;
            }
            return false;
        };
        obj.moveTravaseTree = obj.moveTravaseTree || function (ev, ctx) {
            var components = this.components;
            for (var i = 0; i < components.length; i++) {
                var com = components[i];
                ctx.save();
                if (typeof com.transformView === "function") com.transformView(ctx);
                if (typeof com.moveLayerHandler === "function") com.moveLayerHandler(ev, ctx);
                com.moveTravaseTree(ev, ctx);
                ctx.restore();
            }
        };
        obj.clickTravaseTree = obj.clickTravaseTree || function (ev, ctx) {
            var components = this.components;
            for (var i = 0; i < components.length; i++) {
                var com = components[i];
                ctx.save();
                if (typeof com.transformView === "function") com.transformView(ctx);
                if (typeof com.clickLayerHandler === "function") com.clickLayerHandler(ev, ctx);
                com.clickTravaseTree(ev, ctx);
                ctx.restore();
            }
        };
        this.defineComponent(name, obj);
    };

    App.define("strui", {
        init: function (app, feeback) {
            app.appendComponentConfig(strComponents);
            app.appendComponentConfig(strLayers);
            app.appendPopUpConfig(strPopUps);
            app.appendPageConfig(strPages);

            App.prototype.defineLayer = function () {
                console.warn("layer component must in str-canvas");
            };
            App.setServiceConfig([
                { name: "area", js: "/public/ui/services/common/area.js" },
                { name: "htmlTool", js: "/public/ui/services/common/htmlTool.js" },
                { name: "yDate", js: "/public/ui/services/common/yDate.js" },
                { name: "strTool", js: "/public/ui/services/common/strTool.js" },
                { name: "mdColor", js: "/public/ui/services/common/mdColor.js" },
                { name: "relativeTool", js: "/public/ui/services/canvas/relativeTool.js" },
                { name: "canvasTool", js: "/public/ui/services/canvas/canvasTool.js" },
                { name: "strlayer", js: "/public/ui/services/canvas/strlayer.js" },
                { name: "resource", js: "/public/ui/services/canvas/resource.js" },
                { name: "gradient", js: "/public/ui/services/canvas/gradient.js" },
                { name: "pattern", js: "/public/ui/services/canvas/pattern.js" },
                { name: "marker", js: "/public/ui/services/canvas/marker.js" },
                { name: "helpAnimation", js: "/public/ui/services/canvas/helpAnimation.js" },

                { name: "program", js: "/public/ui/services/webgl/program.js" },
                { name: "euler", js: "/public/ui/services/math/euler.js" },
                { name: "math", js: "/public/ui/services/math/math.js" },
                { name: "matrix3", js: "/public/ui/services/math/matrix3.js" },
                { name: "matrix4", js: "/public/ui/services/math/matrix4.js" },
                { name: "quaternion", js: "/public/ui/services/math/quaternion.js" },
                { name: "vector2", js: "/public/ui/services/math/vector2.js" },
                { name: "vector3", js: "/public/ui/services/math/vector3.js" },
                { name: "vector4", js: "/public/ui/services/math/vector4.js" },
                { name: "matrixStack", js: "/public/ui/services/math/matrixStack.js" },
                { name: "primitive", js: "/public/ui/services/webgl/primitive.js" },
                { name: "webglTool", js: "/public/ui/services/webgl/webglTool.js" },
                { name: "camera", js: "/public/ui/services/webgl/camera.js" }

            ]);

            var script = document.head.querySelector("link");
            var head = document.head;
            var link = document.createElement("link");
            link.rel = "stylesheet";
            link.href = App.join("/public/ui/style/str.css") + "?v=" + App.version;
            head.insertBefore(link, script);
            link.onload = function () {
                if (typeof feeback === "function") feeback();
            };

            [{
                href: "/public/ui/style/str-sm.css",
                str: "only screen and (min-width: 600px)"
            }, {
                href: "/public/ui/style/str-md.css",
                str: "only screen and (min-width: 960px)"
            }, {
                href: "/public/ui/style/str-lg.css",
                str: "only screen and (min-width: 1440px)"
            }, {
                href: "/public/ui/style/str-el.css",
                str: "only screen and (min-width: 1920px)"
            }].forEach(function (item) {
                var link = document.createElement("link");
                link.rel = "stylesheet";
                link.href = App.join(item.href) + "?v=" + App.version;
                link.media = item.str;
                head.insertBefore(link, script);
            })
        }
    })
})